package com.hymjweb.demo.hymj.bill_code_manage.b_master.service;

import com.hymjweb.demo.framework.result.MIniUIGridResultMap;
import com.hymjweb.demo.framework.sys.BaseService;
import com.hymjweb.demo.framework.sys.SysConstant;
import com.hymjweb.demo.framework.util.DataTypeUtil;
import com.hymjweb.demo.framework.util.DateUtil;
import com.hymjweb.demo.hymj.basic_data_manage.xt_airlines.bean.XtAirlinesPojo;
import com.hymjweb.demo.hymj.basic_data_manage.xt_airlines.service.XtAirlinesService;
import com.hymjweb.demo.hymj.bill_code_manage.b_master.bean.BMasterBillCodePojo;
import com.hymjweb.demo.hymj.bill_code_manage.b_master.mapper.BMasterBillCodeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class BMasterBillCodeService extends BaseService {

    @Autowired
    private XtAirlinesService xtAirlinesService;

    @Autowired
    private BMasterBillCodeMapper bMasterBillCodeMapper;


    @Value("${masterBillCode.high.full.zero}")
    private boolean highFullZero;

    @Value("${masterBillCode.base.length}")
    private int baseLength;

    /**
     * 生成的主单号缓存点
     */
    private static Map<String, Object> bMasterBillCodeCache = new HashMap<>();

    /**
     * 根据页面参数生成主单号，无分页
     *
     * @param map
     * @return
     */
    public boolean generateCode(Map<String, Object> map) throws Exception {

        if (map == null || map.isEmpty()) {
            throw new Exception("主单号生成参数错误");
        }

        /**
         * 前台接受的标准参数列表
         * endCode: "100120"
         * keyAgentCompanyId: "383446380553256960"
         * keyGenerateDate: "2020-11-03"
         * keyGenerateDepartmentId: "385640538562428928"
         * keyGenerateUserId: "201910162259560401"
         * keyGenerateUserName: "admin"
         * keyXtAirlinesId: "10013"
         * startCode: "100110"
         */
        String keyGenerateDepartmentId = DataTypeUtil.toNotNullString(map.get("keyGenerateDepartmentId"));
        String keyXtAirlinesId = DataTypeUtil.toNotNullString(map.get("keyXtAirlinesId"));
        String keyGenerateDate = DataTypeUtil.toNotNullString(map.get("keyGenerateDate"));
        String keyGenerateUserId = DataTypeUtil.toNotNullString(map.get("keyGenerateUserId"));
        String startCode = DataTypeUtil.toNotNullString(map.get("startCode"));
        String endCode = DataTypeUtil.toNotNullString(map.get("endCode"));
        String keyAgentCompanyId = DataTypeUtil.toNotNullString(map.get("keyAgentCompanyId"));

        boolean generateStatus = createBillMasterCodeList(startCode, endCode, keyGenerateDepartmentId, keyXtAirlinesId, keyGenerateDate, keyGenerateUserId, keyAgentCompanyId);

        if (generateStatus) {
            return true;
        }

        return false;
    }

    /**
     * 生成主单号
     *
     * @param startCode               开始号码
     * @param endCode                 结束号码
     * @param keyGenerateDepartmentId 领单部门ID
     * @param keyXtAirlinesId         航空公司ID
     * @param keyGenerateDate         领单日期
     * @param keyGenerateUserId       生成人ID
     * @param keyAgentCompanyId       代理人ID（表示该主单归哪个公司使用）
     * @return
     */
    private boolean createBillMasterCodeList(String startCode, String endCode, String keyGenerateDepartmentId, String keyXtAirlinesId, String keyGenerateDate, String keyGenerateUserId, String keyAgentCompanyId) {
        // 将结束单号转为数值
        long endCodeValue = DataTypeUtil.toLong(endCode);

        // 前缀
        int codePrefix = DataTypeUtil.toInt(startCode.substring(0, 7));
        // 后缀
        int codeSuffix = DataTypeUtil.toInt(startCode.substring(7));

        List<BMasterBillCodePojo> bMasterBillCodePojos = new ArrayList<>();

        // 根据缓存name取出对应的缓存列表
        XtAirlinesPojo pojo = xtAirlinesService.fetch(keyXtAirlinesId);
        String towCode = pojo.getTwoCode();

        while (true) {
            long newBillCode = DataTypeUtil.toLong("" + codePrefix + "" + codeSuffix);
            boolean exitFlag = newBillCode <= endCodeValue;
            if (!exitFlag) {
                break;
            }

            /**
             *  `id` varchar(20) NOT NULL COMMENT '分单号ID,就是生成的分单号',
             *   `airlines_id` varchar(20) DEFAULT NULL COMMENT '航空公司ID,关联xt_airlines.id',
             *   `use_status_id` bigint(20) DEFAULT NULL COMMENT '使用状态ID,关联xt_dic.id key=''XT_DIC_USE_STATUS''',
             *   `generate_department_id` varchar(20) DEFAULT NULL COMMENT '生成部门ID,关联xt_department.id',
             *   `generate_date` date DEFAULT NULL COMMENT '生成日期',
             *   `generate_user_id` varchar(20) DEFAULT NULL COMMENT '生成人ID,关联xt_user.id',
             *   `auth_use_department_id` varchar(20) DEFAULT NULL COMMENT '授权使用部门ID,关联xt_department.id,默认是生成部门ID,可以由生成部门修改使用部门ID',
             *   `use_department_id` varchar(20) DEFAULT NULL COMMENT '使用部门ID,关联xt_department.id',
             *   `use_user_id` varchar(20) DEFAULT NULL COMMENT '使用人ID,关联xt_user.id',
             *   `agent_company_id` varchar(20) DEFAULT NULL COMMENT '代理公司ID,关联xt_company.id'
             */

            // 将生成的单号入库
            BMasterBillCodePojo bMasterBillCodePojo = new BMasterBillCodePojo();
            // 高位补0操作
            String newMasterBillCode = getHighFullZeroCode(newBillCode + "");
            bMasterBillCodePojo.setId(towCode + newMasterBillCode);
            bMasterBillCodePojo.setAirlinesId(keyXtAirlinesId);
            bMasterBillCodePojo.setUseStatusId(SysConstant.XT_DIC_USE_STATUS.UNUSED.getId());
            bMasterBillCodePojo.setGenerateDepartmentId(keyGenerateDepartmentId);
            bMasterBillCodePojo.setGenerateDate(DateUtil.strToDate(keyGenerateDate));
            bMasterBillCodePojo.setGenerateUserId(keyGenerateUserId);
            // 默认使用授权部门就是领单时选择的部门
            bMasterBillCodePojo.setAuthUseDepartmentId(keyGenerateDepartmentId);
            bMasterBillCodePojo.setAgentCompanyId(keyAgentCompanyId);

            // 新生成的单号加入集合
            bMasterBillCodePojos.add(bMasterBillCodePojo);

            // 前缀增加
            codePrefix++;
            // 后缀如果小于6就增加，如果大于6则复位
            if (codeSuffix < 6) {
                codeSuffix++;
            } else {
                codeSuffix = 0;
            }
        }

        // 以当前的用户id，存入缓存,如果同一个账号多处登录时，则有可能生成会受影响，但这个概率很低不考虑
        bMasterBillCodeCache.put(keyGenerateUserId, bMasterBillCodePojos);

        return true;
    }

    /**
     * 原始单号高位补0操作
     *
     * @param billCode
     * @return
     */
    private String getHighFullZeroCode(String billCode) {
        StringBuffer fullZeroBillCode = new StringBuffer(billCode);
        if (highFullZero) {
            int fullZeroBillCodeLength = fullZeroBillCode.length();
            if (fullZeroBillCodeLength < baseLength) {
                for (int j = 0; j < baseLength - fullZeroBillCodeLength; j++) {
                    fullZeroBillCode.insert(0, "0");
                }
            }
        }
        return fullZeroBillCode.toString();
    }


    /**
     * 根据用户id显示主单号
     *
     * @param userId
     * @return
     */
    public Object showCode(String userId) {
        if (bMasterBillCodeCache.containsKey(userId)) {
            List<Object> bMasterBillCodePojos = (List<Object>) bMasterBillCodeCache.get(userId);
            MIniUIGridResultMap mIniUIGridResultMap = new MIniUIGridResultMap();
            mIniUIGridResultMap.setData(bMasterBillCodePojos);
            mIniUIGridResultMap.setTotal(bMasterBillCodePojos.size());
            bMasterBillCodeCache.remove(userId);
            return mIniUIGridResultMap;
        }
        return null;
    }

    /**
     * 保存主单号
     *
     * @param rows
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    public boolean saveCode(List<BMasterBillCodePojo> rows) throws Exception {
        if (rows != null && rows.size() > 0) {
            // 获取库中现有的所有单号
            List<BMasterBillCodePojo> list = findAll(null);

            // 转为map,方便判断
            Map<String, BMasterBillCodePojo> maps = convertToMap(list);

            // 将所有要入库的单号加入待入库的List
            List<BMasterBillCodePojo> canSaveList = checkCanSaveBillNativeCode(rows, maps);

            if (canSaveList != null || !canSaveList.isEmpty()) {
                bMasterBillCodeMapper.batchInsert(canSaveList);
                return true;
            }
        }
        return false;
    }

    /**
     * 检测可以保存的单号
     *
     * @param rows
     * @param maps
     * @return
     */
    private List<BMasterBillCodePojo> checkCanSaveBillNativeCode(List<BMasterBillCodePojo> rows, Map<String, BMasterBillCodePojo> maps) {
        List<BMasterBillCodePojo> canSaveList = new ArrayList<>();
        for (BMasterBillCodePojo pojo : rows) {
            if (!maps.containsKey(pojo.getId())) {
                canSaveList.add(pojo);
            }
        }
        return canSaveList;
    }

    /**
     * 查询到的所有单号转为map
     *
     * @param list
     * @return
     */
    private Map<String, BMasterBillCodePojo> convertToMap(List<BMasterBillCodePojo> list) {
        Map<String, BMasterBillCodePojo> map = new HashMap<>();
        for (BMasterBillCodePojo pojo : list) {
            map.put(pojo.getId(), pojo);
        }
        return map;
    }

    /**
     * 根据查询条件查询单号，无分页功能
     *
     * @param map
     * @return
     */
    public List<BMasterBillCodePojo> findAll(Map map) {
        return bMasterBillCodeMapper.findAll(map);
    }

    /**
     * 根据查询条件查询，有分页功能
     *
     * @param map
     * @return
     */
    public Object queryMasterBillCodeList(Map map) {
        this.pageListInit(map);
        List list = findAll(map);
        MIniUIGridResultMap resultMap = this.pageToGrid(list);
        return resultMap;
    }

    /**
     * 根据 id 返回主单号对象
     *
     * @param id
     * @return
     */
    public BMasterBillCodePojo fetch(String id) {
        return bMasterBillCodeMapper.fetch(id);
    }

    /**
     * 根据主单ID，更新其使用状态
     * pojo.setUseStatusId(SysConstant.XT_DIC_USE_STATUS.USED.getId());
     * pojo.setUseDepartmentId(this.getSystemUserDepartment().getId());
     * pojo.setUseUserId(this.getLoginCzyId());
     *
     * @param id
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    public int updateUseStatus(String id, Long userStatusId, String departmentId, String userId) throws Exception {
        if (DataTypeUtil.isEmptyStr(id)) {
            throw new Exception("根据主单号获取主单号对象失败!");
        }
        BMasterBillCodePojo pojo = fetch(id);
        pojo.setUseStatusId(userStatusId);
        pojo.setUseDepartmentId(departmentId);
        pojo.setUseUserId(userId);
        int effectRows = bMasterBillCodeMapper.update(pojo);
        return effectRows;
    }

    /**
     * 主单号授权使用部门调整
     *
     * @param param
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = {Exception.class})
    public boolean adjustUseDepartment(Map<String, Object> param) throws Exception {
        if (param == null || param.isEmpty()) {
            throwException("主单号授权使用部门调整操作参数错误!");
        }
        // {masterBillCode:masterBillCodeIdValue,authorizationUseDepartmentId:useDepartmentIdValue}
        String masterBillCode = DataTypeUtil.toStringObject(param.get("masterBillCode"));
        String authorizationUseDepartmentId = DataTypeUtil.toStringObject(param.get("authorizationUseDepartmentId"));

        if (masterBillCode == null || authorizationUseDepartmentId == null) {
            throwException("主单号授权使用部门调整操作参数错误!");
        }

        int affectRows = bMasterBillCodeMapper.adjustUseDepartment(masterBillCode, authorizationUseDepartmentId);

        if (affectRows > SysConstant.INT_ZERO) {
            return true;
        }

        return false;
    }

    @Transactional(rollbackFor = {Exception.class})
    public int deleteMasterBillCode(Map param) throws Exception {
        if (param == null || param.isEmpty()) {
            throwException("主单号删除操作参数错误!");
        }
        // {deleteMasterBillCodes:canDeleteCodes}
        String deleteMasterBillCodes = DataTypeUtil.toStringObject(param.get("deleteMasterBillCodes"));
        if (deleteMasterBillCodes == null) {
            throwException("主单号删除操作参数错误!");
        }

        String[] deleteMasterBillCodeArray = deleteMasterBillCodes.split(",");
        if (deleteMasterBillCodeArray == null || deleteMasterBillCodeArray.length == 0) {
            throwException("主单号删除操作参数错误!");
        }

        int affectRows = SysConstant.INT_ZERO;
        for (String masterBillCode : deleteMasterBillCodeArray) {
            affectRows += this.delete(masterBillCode);
        }
        return affectRows;
    }

    @Transactional(rollbackFor = {Exception.class})
    public int delete(String masterBillCode) {
        if (DataTypeUtil.isEmptyStr(masterBillCode)) {
            return SysConstant.INT_ZERO;
        }
        return bMasterBillCodeMapper.delete(masterBillCode);
    }


    @Transactional(rollbackFor = {Exception.class})
    public int update(BMasterBillCodePojo bMasterBillCodePojo) throws Exception {
        if(bMasterBillCodePojo==null){
            throwException("更新主单号使用状态参数错误");
        }
        return  bMasterBillCodeMapper.update(bMasterBillCodePojo);
    }
}
